package com.zjq.springsocial.renren.api.impl.json;

import java.io.IOException;

import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.annotate.JsonCreator;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.JsonDeserializer;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.annotate.JsonDeserialize;
import org.codehaus.jackson.type.TypeReference;

import com.zjq.springsocial.renren.api.BasicInformation.HomeTown;
import com.zjq.springsocial.renren.api.BasicInformation.Sex;

@JsonIgnoreProperties(ignoreUnknown = true)
abstract class BasicInformationMixin {

	@JsonCreator
	BasicInformationMixin(
			@JsonProperty("birthday") String birthday,
			@JsonProperty("sex") 
			@JsonDeserialize(using = SexDeserializer.class)
			Sex sex,
			@JsonProperty("homeTown") 
			@JsonDeserialize(using = HomeTownDeserializer.class)
			HomeTown homeTown
	){}
	
	private static class SexDeserializer extends JsonDeserializer<Sex> {
		@Override
		public Sex deserialize(JsonParser jp, DeserializationContext ctxt)
				throws IOException, JsonProcessingException {
			try {
				return Sex.valueOf(jp.getText().toUpperCase());
			} catch (IllegalArgumentException e) {
				return Sex.MALE;
			}
		}
	}
	
	private class HomeTownDeserializer extends JsonDeserializer<HomeTown> {
		@Override
		public HomeTown deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
			ObjectMapper mapper = new ObjectMapper();
			mapper.setDeserializationConfig(ctxt.getConfig());
			jp.setCodec(mapper);
			if (jp.hasCurrentToken()) {
				JsonNode dataNode = jp.readValueAsTree();
				if (dataNode != null) {
					return (HomeTown) mapper.readValue(dataNode,new TypeReference<HomeTown>(){});
				}
			}
			return null;
		}
	}
}
